#include "BaseType.h"
#include "Tracer.h"
using namespace std;
using namespace libemb;

/**
 * 设计模式：
 * 1.把命令接收者的一组类似行为进行抽象，将其封装成对象(命令)。
 * 2.将命令请求者(客户)与命令接收者解耦,命令请求者只需要提供要执行的命令即可。
 * 3.新增请求不需要修改原来的类，只需要封装一个新的命令用来执行新增的请求即可。
 * 适用场景：
 * 1. 可以实现命令撤销，命令日志及重播
 **/

//厨师:命令接收者，不需要知道顾客是谁，也不需要知道服务员是谁，只要接收命令并完成就好
class Chef{
DECL_CLASSNAME(Chef)
private:
    std::string m_name;
public:
    Chef(const std::string& name)
    {
        m_name = name;
    }
    void makeFish()
    {
        TRACE_INFO_CLASS("%s is making fish",VSTR(m_name));
    }
    void makeChicken()
    {
        TRACE_INFO_CLASS("%s is making Chicken",VSTR(m_name));
    }

    void makeNothing()
    {
        TRACE_INFO_CLASS("%s is making Nothing",VSTR(m_name));
    }
};

//命令：封装请求，指定命令接收者，并实现命令的具体行为
class Command{
DECL_CLASSNAME(Command)
protected:
    std::shared_ptr<Chef> m_chef;
public:
    virtual void execute()=0;
    virtual void undo()=0;
};

//制作鱼的命令
class MakeFish:public Command{
DECL_CLASSNAME(MakeFish)
public:
    MakeFish()
    {
        m_chef = std::make_shared<Chef>("Fish Chef");
    }
    void execute() override
    {
        m_chef->makeFish();
    }
    void undo() override
    {
        m_chef->makeNothing();
    }
};

//制作鸡的命令
class MakeChicken:public Command{
DECL_CLASSNAME(MakeChicken)
public:
    MakeChicken()
    {
        m_chef = std::make_shared<Chef>("Chicken Chef");
    }
    void execute() override
    {
        m_chef->makeChicken();
    }
    void undo() override
    {
        m_chef->makeNothing();
    }
};

//服务员: 命令调用者,只管调用封装好的命令即可，不需要关心这个命令由谁来执行，怎么执行
class Waiter{
DECL_CLASSNAME(Waiter)
private:
    std::shared_ptr<MakeFish> m_fish;
    std::shared_ptr<MakeChicken> m_chicken;
    std::vector<std::shared_ptr<Command>> m_commands;
public:
    Waiter()
    {
        m_fish = std::make_shared<MakeFish>();
        m_chicken = std::make_shared<MakeChicken>();
    }
    void orderFish()
    {
        m_fish->execute();
        m_commands.push_back(m_fish);
    }

    void orderChicken()
    {
        m_chicken->execute();
        m_commands.push_back(m_chicken);
    }

    //撤销命令
    void cancel()
    {
        if (!m_commands.empty())
        {
            auto command = m_commands.back();
            command->undo();
            m_commands.pop_back();
        }
        else
        {
            TRACE_INFO_CLASS("You wanna nothing, Are you kidding me!");
        }
    }
};


int main()
{
    Tracer::getInstance().setLevel(TRACE_LEVEL_DBG);
	Tracer::getInstance().addSink(std::make_shared<STDSink>());

    //顾客：命令请求者,只需要跟Waiter打交道,不需要知道这个菜由谁做，怎么做
    Waiter waiter;
    waiter.orderFish();
    waiter.orderChicken();
    waiter.cancel();
    waiter.cancel();
    waiter.cancel();//没有命令可以撤销

    return RC_OK;
}